#' Calculate the Area Under the Fluorescence Rise Curve
#'
#' This function computes a specific area related to the fluorescence rise curve
#' (from the OJIP test) using a trapezoidal integration method. It is designed
#' for high-frequency data (e.g., 250Hz) and calculates the area between the
#' actual curve and a rectangle defined by the minimum and maximum values of the
#' signal and time (on a log scale).
#'
#' @param df A data frame. It must contain the columns: `MILLI_SEC` (time in
#'   milliseconds), `FLUOR` (PAM fluorescence signal), and `DC` (continuous
#'   fluorescence signal).
#' @param use_PAM A logical value. If `TRUE` (default), the function uses the
#'   `FLUOR` column for calculations. If `FALSE`, it uses the `DC` column.
#'
#' @return A numeric scalar representing the calculated area. Specifically, it
#'   returns the value of `a_total - auc`, where `a_total` is the area of the
#'   rectangle and `auc` is the area under the curve from the start to the peak.
#'
#' @details
#' The calculation proceeds as follows:
#' 1.  The time column (`MILLI_SEC`) is converted to a natural logarithm scale
#'     (`logs`).
#' 2.  The function identifies the index of the peak value in the selected
#'     fluorescence signal column (`FLUOR` or `DC`).
#' 3.  The data frame is truncated to include only the data points from the start
#'     up to and including the peak.
#' 4.  The area under the truncated curve (`auc`) is computed using trapezoidal
#'     integration on the log-time scale.
#' 5.  The area of a rectangle (`a_total`) is computed, with height equal to the
#'     difference between the maximum and minimum signal values, and width equal
#'     to the difference between the maximum and minimum log-time values.
#' 6.  The result is the difference between `a_total` and `auc`.
#'
#' @section Warning:
#' Ensure that your data frame `df` is sorted by time (`MILLI_SEC`) in ascending
#' order. The function does not perform sorting and incorrect order will lead to
#' invalid integration results.
#'
#' @examples
#' \dontrun{
#' library(jiptest)
#' # Load your data (ensure columns are named MILLI_SEC, FLUOR, DC)
#' data = load_your_data_function("your_data_file.xlsx")
#'
#' # Calculate area using the PAM signal (FLUOR column)
#' area_pam = area_cal(data, use_PAM = TRUE)
#'
#' # Calculate area using the DC signal (DC column)
#' area_dc = area_cal(data, use_PAM = FALSE)
#' }
#'
#' @export
#' @importFrom zoo rollmean

area_cal = function(df, use_PAM = TRUE) {
  # Input validation
  required_cols = c("MILLI_SEC", "FLUOR", "DC")
  if (!all(required_cols %in% colnames(df))) {
    missing_cols = setdiff(required_cols, colnames(df))
    stop(paste("The input data frame is missing required columns:",
               paste(missing_cols, collapse = ", ")))
  }
  
  if (!is.logical(use_PAM) || length(use_PAM) != 1) {
    stop("`use_PAM` must be a single logical value (TRUE or FALSE).")
  }
  
  # Select the appropriate signal column and calculate its peak index
  if (use_PAM) {
    signal_col = "FLUOR"
  } else {
    signal_col = "DC"
  }
  
  signal_data = df[[signal_col]]
  peak_index = which.max(signal_data)
  
  if (peak_index == 1) {
    warning("The peak of the ", signal_col, " signal is at the first data point. ",
            "The calculated area may not be meaningful.")
  }
  
  # Truncate data to the region from start to peak
  df_truncated = df[1:peak_index, , drop = FALSE]
  
  # Calculate log(time)
  df_truncated$logs = log(df_truncated$MILLI_SEC)
  
  # Calculate AUC using trapezoidal integration
  auc = with(df_truncated, sum(diff(logs) * zoo::rollmean(get(signal_col), 2)))
  
  # Calculate the total rectangular area
  max_signal = max(df_truncated[[signal_col]])
  min_signal = min(df_truncated[[signal_col]])
  max_log_time = max(df_truncated$logs)
  min_log_time = min(df_truncated$logs)
  
  a_total = (max_signal - min_signal) * (max_log_time - min_log_time)
  
  # Return the desired area
  return(a_total - auc)
}

